package com.iwdnb.gkgz.application.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSON;

import cn.hutool.core.date.DateUtil;
import com.google.common.collect.Lists;
import com.iwdnb.bmnf.common.dingtalk.DingTalkService;
import com.iwdnb.bmnf.common.service.CacheService;
import com.iwdnb.bmnf.common.utils.BooleanUtils;
import com.iwdnb.gkgz.application.service.StockDayDataSerivce;
import com.iwdnb.gkgz.application.service.StockEmotionService;
import com.iwdnb.gkgz.common.constant.CacheConstants;
import com.iwdnb.gkgz.common.model.dto.StockDayData;
import com.iwdnb.gkgz.common.model.dto.StockEmotion;
import com.iwdnb.gkgz.common.model.dto.StockFenshiData;
import com.iwdnb.gkgz.common.utils.BigDecimalUtils;
import com.iwdnb.gkgz.common.utils.DateUtils;
import com.iwdnb.gkgz.common.utils.EmotionAnalysis;
import com.iwdnb.gkgz.common.utils.EmotionAnalysis.EmotionData;
import com.iwdnb.gkgz.common.utils.StockFenshiUtils;
import com.iwdnb.gkgz.common.utils.StockUtils;
import com.iwdnb.gkgz.common.utils.WorkDayUtils;
import com.iwdnb.gkgz.infrastructure.dao.client.MairuiClient;
import com.iwdnb.gkgz.infrastructure.dao.repo.StockDayDataRepository;
import com.iwdnb.gkgz.infrastructure.dao.repo.StockFenshiRepository;
import com.iwdnb.gkgz.infrastructure.dao.repo.StockRepository;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class StockEmotionServiceImpl implements StockEmotionService {
    @Autowired
    private StockDayDataSerivce stockDayDataSerivce;
    @Autowired
    private DingTalkService dingTalkService;
    @Autowired
    private CacheService cacheService;

    @Autowired
    private StockDayDataRepository stockDayDataRepository;
    @Autowired
    private Executor executor;
    @Autowired
    private MairuiClient mairuiClient;
    @Autowired
    private StockRepository stockRepository;
    @Autowired
    private StockFenshiRepository stockFenshiRepository;
    private String DING_TALK_URL = "https://oapi.dingtalk"
        + ".com/robot/send?access_token=a079cbbaa764379fb898c2c16bd9be407966dfba41e19f5b25a7b015240c0901";

    @Override
    public void initEmotions(String begin, String end, String loadDataFlag) {
        log.info("initEmotions start");
        if (BooleanUtils.isTrue(loadDataFlag)) {
            Map<String, List<StockDayData>> stockDayDataMap = initEmotionStockDayDataMap(begin, end);
        }
        //转换成按日期排列的map
        Date date = DateUtil.parseDate(begin);
        Date endDate = DateUtil.parseDate(end);
        if (!WorkDayUtils.isWorkDay(date)) {
            date = WorkDayUtils.getNextWorkDay(date);
        }
        int markEmotion = EmotionAnalysis.COLD_EMOTION;
        for (int i = 0; i < 100000; i++) {
            String dateStr = DateUtil.formatDate(date);
            String cacheKey = CacheConstants.STOCK_EMOTION_STOCK_CACHE_PREFIX + dateStr;
            String cacheContent = cacheService.get(cacheKey);
            if (StringUtils.isBlank(cacheContent)) {
                log.info("{}-emotion no data.", dateStr);
                date = WorkDayUtils.getNextWorkDay(date);
                if (date.after(endDate)) {
                    break;
                }
                continue;
            }
            List<StockDayData> stockDayDataList = JSON.parseArray(cacheContent, StockDayData.class);
            cacheKey = CacheConstants.STOCK_EMOTION_CACHE_PREFIX + DateUtil.formatDate(date);
            StockEmotion stockEmotion = cacheService.get(cacheKey);
            if (Objects.nonNull(stockEmotion)) {
                //log.info("{}-emotion cached:{}-{}", date, stockEmotion.getOpen(), stockEmotion.getClose());
                //continue;
            }
            if (CollectionUtils.isNotEmpty(stockDayDataList)) {
                EmotionData emotionData = EmotionAnalysis.caculateOpenEmotion(stockDayDataList);
                Integer openEmotion = emotionData.getEmotionValue();
                if (EmotionAnalysis.isMarkEmotion(openEmotion)) {
                    markEmotion = openEmotion;
                }
                //添加开盘情绪
                stockEmotion = new StockEmotion();
                stockEmotion.setOpen(openEmotion);

                StockEmotion openStockEmotion = new StockEmotion();
                openStockEmotion.setDatetime(date + " 09:30:00");
                openStockEmotion.setClose(openEmotion);
                openStockEmotion.setCurrentValue(emotionData.getCurrentValue());
                openStockEmotion.setMinValue(emotionData.getMinValue());
                openStockEmotion.setLowValue(emotionData.getLowValue());
                openStockEmotion.setHighValue(emotionData.getHighValue());
                openStockEmotion.setMaxValue(emotionData.getMaxValue());
                stockEmotion.addEmotion(openStockEmotion, markEmotion);

                emotionData = EmotionAnalysis.caculateEmotion(stockDayDataList);
                Integer closeEmotion = emotionData.getEmotionValue();
                if (EmotionAnalysis.isMarkEmotion(closeEmotion)) {
                    markEmotion = closeEmotion;
                }
                StockEmotion closeStockEmotion = new StockEmotion();
                closeStockEmotion.setDatetime(date + " 15:00:00");
                closeStockEmotion.setClose(closeEmotion);
                closeStockEmotion.setCurrentValue(emotionData.getCurrentValue());
                closeStockEmotion.setMinValue(emotionData.getMinValue());
                closeStockEmotion.setLowValue(emotionData.getLowValue());
                closeStockEmotion.setHighValue(emotionData.getHighValue());
                closeStockEmotion.setMaxValue(emotionData.getMaxValue());
                stockEmotion.setClose(closeEmotion);
                stockEmotion.addEmotion(closeStockEmotion, markEmotion);
                cacheService.put(cacheKey, stockEmotion);
                log.info("{}-emotion:{}-{}", date, openEmotion, closeEmotion);
            }
            date = WorkDayUtils.getNextWorkDay(date);
            if (date.after(endDate)) {
                break;
            }
        }
        log.info("initEmotions finished");

    }

    @Override
    public StockEmotion getPredicateStockEmotion(String date) {
        Date beforeDate = WorkDayUtils.getBeforeWorkDay(DateUtil.parseDate(date), 1);
        String beforeDateStr = DateUtil.formatDate(beforeDate);
        String cacheKey = CacheConstants.STOCK_EMOTION_CACHE_PREFIX + beforeDateStr;
        StockEmotion stockEmotion = cacheService.get(cacheKey);
        //如果缓存没有则重新计算前一天的情绪值
        if (Objects.isNull(stockEmotion)) {
            initEmotions(beforeDateStr, beforeDateStr, BooleanUtils.TRUE);
        }
        return cacheService.get(cacheKey);
    }

    @Override
    public void refreshRealtimeStockEmotion() {
        Date date = new Date();
        String dateStr = DateUtil.formatDate(date);
        String time = DateUtil.formatTime(date);
        //获取当天的情绪股票列表
        List<StockDayData> stockDayDataList = getEmotionRealtimeStockList(dateStr);
        String cacheKey = CacheConstants.STOCK_EMOTION_CACHE_PREFIX + dateStr;
        StockEmotion stockEmotion = cacheService.get(cacheKey);
        if (Objects.isNull(stockEmotion)) {
            //获取前一天的情绪值
            StockEmotion predicateEmotion = getPredicateStockEmotion(dateStr);
            //计算实时情绪值
            stockEmotion = initRealtimeStockEmotion(stockDayDataList, date, predicateEmotion.getMarkEmotion());
        }
        //刷新当前情绪
        int markEmotion = stockEmotion.getMarkEmotion();
        int beforeCloseEmotion = stockEmotion.getClose();
        EmotionData emotionData = EmotionAnalysis.caculateEmotion(stockDayDataList);
        int closeEmotion = emotionData.getEmotionValue();
        if (EmotionAnalysis.isMarkEmotion(closeEmotion)) {
            markEmotion = closeEmotion;
        }
        StockEmotion closeStockEmotion = new StockEmotion();
        closeStockEmotion.setDatetime(dateStr + " " + time);
        closeStockEmotion.setClose(closeEmotion);
        closeStockEmotion.setCurrentValue(emotionData.getCurrentValue());
        closeStockEmotion.setMinValue(emotionData.getMinValue());
        closeStockEmotion.setLowValue(emotionData.getLowValue());
        closeStockEmotion.setHighValue(emotionData.getHighValue());
        closeStockEmotion.setMaxValue(emotionData.getMaxValue());
        closeStockEmotion.setClose(closeEmotion);
        stockEmotion.addEmotion(closeStockEmotion, markEmotion);
        //int emotionRange = Math.abs(closeEmotion - beforeCloseEmotion);
        log.info("{}-实时情绪:{},主体情绪:{}", dateStr + " " + time, closeEmotion, markEmotion);
        //冰点、热点处理
        dealMarkEmotion(closeStockEmotion, stockEmotion.getList().get(0), date);
        cacheService.put(cacheKey, stockEmotion);
    }

    @Override
    public StockEmotion getFenshiStockEmotion(String dateStr) {
        boolean isToday = StringUtils.equals(dateStr, DateUtil.formatDate(new Date()));
        Date date = DateUtil.parseDate(dateStr);
        List<String> codeList = getStockCodeList();
        Map<String, List<StockDayData>> stockDayDataMap = new LinkedHashMap<>();
        List<StockDayData> beforeStockDayDataList = getBeforeDayDataList(dateStr);
        //初始化分时k线数据
        for (String code : codeList) {
            List<StockDayData> stockDayDataList = null;
            if (isToday) {
                stockDayDataList = StockFenshiUtils.getFenshiList(code);
            } else {
                StockFenshiData stockFenshiData = stockFenshiRepository.queryFenshiList(code, dateStr);
                if (Objects.isNull(stockFenshiData)) {
                    continue;
                }
                stockDayDataList = stockFenshiData.getFenshiList();
            }
            if (CollectionUtils.isEmpty(stockDayDataList)) {
                continue;
            }
            StockDayData beforeData = beforeStockDayDataList.stream().filter(
                t -> Objects.nonNull(t) && t.getCode().equals(code)).findAny().orElse(null);
            if (Objects.isNull(beforeData)) {
                continue;
            }

            for (StockDayData stockDayData : stockDayDataList) {
                stockDayData.setBeforeClosePrice(beforeData.getClosePrice());
                String datetime = stockDayData.getDatetime();
                List<StockDayData> list = stockDayDataMap.get(datetime);
                if (CollectionUtils.isEmpty(list)) {
                    list = new ArrayList<>();
                }
                list.add(stockDayData);
                stockDayDataMap.put(datetime, list);
            }
        }
        //
        StockEmotion predicateEmotion = getPredicateStockEmotion(dateStr);
        int markEmotion = predicateEmotion.getMarkEmotion();
        List<StockDayData> stockDayDataList = stockDayDataMap.get(dateStr + " 09:30:00");
        EmotionData emotionData = EmotionAnalysis.caculateOpenEmotion(stockDayDataList);
        Integer openEmotion = emotionData.getEmotionValue();
        if (EmotionAnalysis.isMarkEmotion(openEmotion)) {
            markEmotion = openEmotion;
        }
        StockEmotion stockEmotion = new StockEmotion();
        stockEmotion.setOpen(openEmotion);
        StockEmotion openStockEmotion = new StockEmotion();
        openStockEmotion.setDatetime(dateStr + " 09:30:00");
        openStockEmotion.setClose(openEmotion);
        openStockEmotion.setCurrentValue(emotionData.getCurrentValue());
        openStockEmotion.setMinValue(emotionData.getMinValue());
        openStockEmotion.setLowValue(emotionData.getLowValue());
        openStockEmotion.setHighValue(emotionData.getHighValue());
        openStockEmotion.setMaxValue(emotionData.getMaxValue());
        stockEmotion.addEmotion(openStockEmotion, markEmotion);
        for (String datetime : stockDayDataMap.keySet()) {
            stockDayDataList = stockDayDataMap.get(datetime);
            //cacheKey = CacheConstants.STOCK_EMOTION_CACHE_PREFIX + DateUtil.formatDate(date);
            //StockEmotion stockEmotion = cacheService.get(cacheKey);
            //if (Objects.nonNull(stockEmotion)) {
            //    //log.info("{}-emotion cached:{}-{}", date, stockEmotion.getOpen(), stockEmotion.getClose());
            //    //continue;
            //}
            if (CollectionUtils.isNotEmpty(stockDayDataList)) {
                emotionData = EmotionAnalysis.caculateEmotion(stockDayDataList);
                Integer emotion = emotionData.getEmotionValue();
                if (EmotionAnalysis.isMarkEmotion(emotion)) {
                    markEmotion = emotion;
                }

                StockEmotion currentStockEmotion = new StockEmotion();
                currentStockEmotion.setDatetime(datetime);
                currentStockEmotion.setClose(emotion);
                currentStockEmotion.setCurrentValue(emotionData.getCurrentValue());
                currentStockEmotion.setMinValue(emotionData.getMinValue());
                currentStockEmotion.setLowValue(emotionData.getLowValue());
                currentStockEmotion.setHighValue(emotionData.getHighValue());
                currentStockEmotion.setMaxValue(emotionData.getMaxValue());
                stockEmotion.addEmotion(currentStockEmotion, markEmotion);
                log.info("{}-fenshiEmotion:{}", datetime, emotion);
            }
        }
        String cacheKey = CacheConstants.STOCK_EMOTION_CACHE_PREFIX + dateStr;
        cacheService.put(cacheKey, stockEmotion);
        return stockEmotion;
    }

    @Override
    public StockEmotion getStockEmotion(String dateStr) {
        String cacheKey = CacheConstants.STOCK_EMOTION_CACHE_PREFIX + dateStr;
        return cacheService.get(cacheKey);
    }

    @Override
    public StockEmotion getColdEmotion(Date datetime) {
        String date = DateUtil.formatDate(datetime);
        StockEmotion stockEmotion = getStockEmotion(date);
        if (Objects.isNull(stockEmotion)) {
            return null;
        }
        List<StockEmotion> emotionList = stockEmotion.getList().stream().filter(
            t -> DateUtils.beforeOrEquals(DateUtil.parseDateTime(t.getDatetime()), datetime)).collect(
            Collectors.toList());
        if(CollectionUtils.isEmpty(emotionList)){
            return null;
        }
        StockEmotion openEmotion = emotionList.get(0);
        StockEmotion coldEmotion = null;
        for (StockEmotion emotion : emotionList) {
            //没遇到冰点之前,依次遍历冰点情绪
            if (Objects.isNull(coldEmotion)) {
                if (EmotionAnalysis.isColdEmotion(emotion.getMarkEmotion())) {
                    coldEmotion = emotion;
                }
            } else {
                //遇到冰点之后,依次遍历获取热点情绪,获取到热点情绪，就移除冰点信息
                if (EmotionAnalysis.isActiveEmotion(emotion.getMarkEmotion())) {
                    coldEmotion = null;
                }

            }
            //当前均涨幅比开盘高1个点,移除冰点信息
            BigDecimal rate = BigDecimalUtils.subtract(emotion.getCurrentValue(), openEmotion.getCurrentValue());
            if (BigDecimalUtils.isGe(rate, BigDecimal.ONE)) {
                coldEmotion = null;
            }
        }
        return coldEmotion;
    }

    private void dealMarkEmotion(StockEmotion stockEmotion, StockEmotion openStockEmotion,
        Date date) {
        //获取与开盘价涨幅差值
        BigDecimal rate = BigDecimalUtils.subtract(stockEmotion.getCurrentValue(), openStockEmotion.getCurrentValue());
        int emotion = stockEmotion.getMarkEmotion();
        String dateStr = DateUtil.formatDate(date);
        String cacheKey = CacheConstants.STOCK_EMOTION_MARK_CACHE_PREFIX + dateStr;
        StockEmotion cacheStockEmotion = cacheService.get(cacheKey);
        //冰点处理
        if (EmotionAnalysis.isColdEmotion(emotion)) {
            //如果缓存中的情绪是热点情绪,那就发出通知
            if (Objects.isNull(cacheStockEmotion) || EmotionAnalysis.isActiveEmotion(
                cacheStockEmotion.getMarkEmotion())) {
                String datetime = DateUtil.formatDateTime(date);
                cacheService.put(cacheKey, stockEmotion);
                dingTalkService.sendMessage(DING_TALK_URL, "情绪冰点通知:" + datetime + "-情绪进入冰点,赶紧抛售持有股票,禁止买入股票",
                    Lists.newArrayList());
            }
        } else if (EmotionAnalysis.isActiveEmotion(emotion)) {
            //热点处理
            //如果缓存中的情绪是冰点情绪,那就发出通知
            if (Objects.isNull(cacheStockEmotion) || EmotionAnalysis.isColdEmotion(
                cacheStockEmotion.getMarkEmotion())) {
                String datetime = DateUtil.formatDateTime(date);
                cacheService.put(cacheKey, stockEmotion);
                dingTalkService.sendMessage(DING_TALK_URL, "情绪热点通知:" + datetime + "-情绪进入热点,可买入股票",
                    Lists.newArrayList());
            }
        }
        //特殊处理
        if (BigDecimalUtils.isGe(rate, BigDecimal.ONE)) {
            //当前均涨幅比开盘高1个点,通知情绪转暖
            if (Objects.isNull(cacheStockEmotion) || EmotionAnalysis.isColdEmotion(
                cacheStockEmotion.getMarkEmotion())) {
                String datetime = DateUtil.formatDateTime(date);
                cacheService.put(cacheKey, stockEmotion);
                dingTalkService.sendMessage(DING_TALK_URL, "情绪转暖通知:" + datetime + "-情绪转暖,可买入股票",
                    Lists.newArrayList());
            }
        }
    }

    private StockEmotion initRealtimeStockEmotion(List<StockDayData> stockDayDataList, Date date,
        int markEmotion) {
        String dateStr = DateUtil.formatDate(date);
        String timeStr = DateUtil.formatTime(date);
        if (CollectionUtils.isEmpty(stockDayDataList)) {
            return null;
        }
        EmotionData emotionData = EmotionAnalysis.caculateOpenEmotion(stockDayDataList);
        Integer openEmotion = emotionData.getEmotionValue();
        if (EmotionAnalysis.isMarkEmotion(openEmotion)) {
            markEmotion = openEmotion;
        }
        //添加开盘情绪
        StockEmotion stockEmotion = new StockEmotion();
        stockEmotion.setOpen(openEmotion);
        StockEmotion openStockEmotion = new StockEmotion();
        openStockEmotion.setDatetime(dateStr + " 09:25:00");
        openStockEmotion.setClose(openEmotion);
        openStockEmotion.setCurrentValue(emotionData.getCurrentValue());
        openStockEmotion.setMinValue(emotionData.getMinValue());
        openStockEmotion.setLowValue(emotionData.getLowValue());
        openStockEmotion.setHighValue(emotionData.getHighValue());
        openStockEmotion.setMaxValue(emotionData.getMaxValue());
        stockEmotion.addEmotion(openStockEmotion, markEmotion);
        emotionData = EmotionAnalysis.caculateEmotion(stockDayDataList);
        Integer closeEmotion = EmotionAnalysis.caculateEmotion(stockDayDataList).getEmotionValue();
        if (EmotionAnalysis.isMarkEmotion(closeEmotion)) {
            markEmotion = closeEmotion;
        }
        StockEmotion closeStockEmotion = new StockEmotion();
        closeStockEmotion.setDatetime(dateStr + " " + timeStr);
        closeStockEmotion.setClose(closeEmotion);
        closeStockEmotion.setCurrentValue(emotionData.getCurrentValue());
        closeStockEmotion.setMinValue(emotionData.getMinValue());
        closeStockEmotion.setLowValue(emotionData.getLowValue());
        closeStockEmotion.setHighValue(emotionData.getHighValue());
        closeStockEmotion.setMaxValue(emotionData.getMaxValue());
        stockEmotion.setClose(closeEmotion);
        stockEmotion.addEmotion(closeStockEmotion, markEmotion);
        String cacheKey = CacheConstants.STOCK_EMOTION_CACHE_PREFIX + dateStr;
        cacheService.put(cacheKey, stockEmotion);
        log.info("{}-开盘情绪{},主体情绪:{}", dateStr, closeEmotion, markEmotion);
        return stockEmotion;
    }

    /**
     * 获取当天的情绪股票列表
     *
     * @param date
     * @return
     */
    private List<StockDayData> getEmotionRealtimeStockList(String date) {
        List<String> codeList = getStockCodeList();
        //拿到前一天的数据
        List<StockDayData> beforeStockDayDataList = getBeforeDayDataList(date);
        if (CollectionUtils.isEmpty(beforeStockDayDataList)) {
            return null;
        }
        //获取实时数据
        List<StockDayData> stockDayDataList = StockUtils.getRealtimeStockDataList(codeList);
        List<StockDayData> list = new ArrayList<>();
        for (StockDayData stockDayData : stockDayDataList) {
            StockDayData beforeData = beforeStockDayDataList.stream().filter(
                t -> t.getCode().equals(stockDayData.getCode())).findAny().orElse(null);
            if (Objects.isNull(beforeData)) {
                continue;
            }
            //设置前一日的收盘价
            stockDayData.setBeforeClosePrice(beforeData.getClosePrice());
            list.add(stockDayData);
        }
        String cacheKey = CacheConstants.STOCK_EMOTION_STOCK_CACHE_PREFIX + date;
        cacheService.put(cacheKey, JSON.toJSONString(list));
        return list;
    }

    private List<StockDayData> getBeforeDayDataList(String date) {
        Date beforeDate = WorkDayUtils.getBeforeWorkDay(DateUtil.parseDate(date), 1);
        String beforeDateStr = DateUtil.formatDate(beforeDate);
        String cacheKey = CacheConstants.STOCK_EMOTION_STOCK_CACHE_PREFIX + beforeDateStr;
        String cacheContent = cacheService.get(cacheKey);
        List<StockDayData> beforeStockDayDataList = null;
        if (StringUtils.isNotBlank(cacheContent)) {
            beforeStockDayDataList = JSON.parseArray(cacheContent, StockDayData.class);
        } else {
            log.error("{}-emotion no data.", beforeDateStr);
            Map<String, List<StockDayData>> map = initEmotionStockDayDataMap(beforeDateStr, beforeDateStr);
            beforeStockDayDataList = map.get(beforeDateStr);
        }
        return beforeStockDayDataList;
    }

    private Map<String, List<StockDayData>> initEmotionStockDayDataMap(String begin, String end) {
        Map<String, List<StockDayData>> stockDayDataMap = new HashMap<>();
        List<String> codeList = getStockCodeList();
        //System.out.println(StringUtils.join(codeList, ","));
        CountDownLatch latch = new CountDownLatch(codeList.size());
        for (String code : codeList) {
            executor.execute(() -> {
                stockDayDataSerivce.loadStockDayData(code, begin, end);
                List<StockDayData> stockDayDataList = stockDayDataRepository.queryAllByDateRange(code, begin, end);
                stockDayDataMap.put(code, stockDayDataList);
                latch.countDown();
                log.info("initEmotion loadStockDayData CountDownLatch:{}", latch.getCount());
            });
        }
        try {
            latch.await(30, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //转换成按日期排列的map
        Date date = DateUtil.parseDate(begin);
        Date endDate = DateUtil.parseDate(end);
        if (!WorkDayUtils.isWorkDay(date)) {
            date = WorkDayUtils.getNextWorkDay(date);
        }
        Map<String, List<StockDayData>> dateDataMap = new LinkedHashMap<>();
        for (int i = 0; i < 100000; i++) {
            String dateStr = DateUtil.formatDate(date);
            List<StockDayData> dataList = new ArrayList<>();
            for (String code : stockDayDataMap.keySet()) {
                List<StockDayData> stockDayDataList = stockDayDataMap.get(code);
                if (CollectionUtils.isEmpty(stockDayDataList)) {
                    log.error("{}-stockDayData is null", code);
                }
                StockDayData data = StockUtils.getStockDayData(stockDayDataList, dateStr);
                if (Objects.nonNull(data)) {
                    dataList.add(data);
                }
            }
            dateDataMap.put(dateStr, dataList);
            String cacheKey = CacheConstants.STOCK_EMOTION_STOCK_CACHE_PREFIX + dateStr;
            cacheService.put(cacheKey, JSON.toJSONString(dataList));

            date = WorkDayUtils.getNextWorkDay(date);
            if (date.after(endDate)) {
                break;
            }
        }

        return dateDataMap;
    }

    private List<String> getStockCodeList() {
        //List<Stock> stockList = mairuiClient.getStockListByZs("zhishu_000905");
        //return stockList.stream().map(Stock::getCode).collect(Collectors.toList());
        return Lists.newArrayList(STOCK_CODE_LIST.split(","));
    }

    private static final String STOCK_CODE_LIST =
        "sh603398,sz000869,sz002183,sz002127,sz002275,sz002081,sz301205,sz300482,sz300620,sz002250,sz002985,"
            + "sz002096,sz002705,sz300261,sz002265,sz301246,sz000837,sz000415,sz300182,sz300182,sz301262,sz001287,"
            + "sh601326,sh600976,sz002275,sz000719,sz002458,sz002221,sh600409,sh600195,sz002265,sh600782,sh600601,"
            + "sz000869,sz300261,sz301358,sz301376,sz002183,sz000420,sz300741,sh600409,sz002183,sz002250,sz000420,"
            + "sz002275,sz301262,sz301325,sz002866,sh603719,sh603100,sz000552,sz000821,sh601101,sh603477,sh603057,"
            + "sh601022,sz301267,sz300820,sh603871,sz301363,sh600064,sz301327,sz301171,sz300630,sh600633,sz301165,"
            + "sz002416,sz300002,sz002583,sz002424,sz002434,sz002701,sh603719,sz301363,sh600201,sh601019,sh603983,"
            + "sh603477,sh605020,sh603281,sz000686,sz002124,sz001236,sz301095,sz001301,sz301268,sz002003,sz300315,"
            + "sh603297,sz002006,sh600403,sh603123,sz002011,sh600400,sh600508,sz300332,sz301219,sz300953,sz002946,"
            + "sz300358,sz002317,sz301238,sz301175,sz001270,sz002004,sh600120,sz002174,sh600811,sh603032,sh600478,"
            + "sz301268,sh603297,sh600403,sz002317,sz301216,sh601860,sz001258,sz300315,sz301216,sh600478,sh600403,"
            + "sz300459,sz002724,sz300443,sz000681,sh603567,sh603396,sz301089,sh600691,sz301080,sz301180,sz300772,"
            + "sh600869,sz300133,sz301060,sh603055,sh600691,sz002038,sz002724,sz301180,sz301080,sh600675,sz300772,"
            + "sh600888,sz000681,sh601702,sh600610,sh603306,sz300133,sz301047,sz000681,sh601702,sh600610,sh603306,"
            + "sz300133,sz301047,sh603995,sz000966,sh600007,sh600877,sz301015,sz002612,sz003039,sz300671,sh600098,"
            + "sh603171,sz003040,sz000061,sz002456,sz000860,sz002839,sh600586,sz000762,sh601208,sh603033,sh605090,"
            + "sz300432,sz002217,sh605365,sz002773,sh601921,sz300027,sh601528,sz300035,sh600428,sz002941,sz002891,"
            + "sh600073,sz002807,sz003009,sz300860,sh600320,sz002544,sz000543,sz003012,sz300470,sz300910,sh601212,"
            + "sz002190,sz000712,sh603877,sh605009,sh605338,sz002993,sz003009,sh601609,sz000848,"
            + "sh600996,sz002979,sh603766,sh603025,sz300841,sz300639,sz300856,sz002987,sz300767,sh601678,sz300738,"
            + "sz300855,sz002847,sh603129,sz300206,sh603566,sz002990,sh603301,sh603208,sh600452,sz002201,sh600223,"
            + "sz002573,sz002961,sz002706,sz300762,sz300455,sh603530,sz000403,sh601001,sz002959,sh600510,sz002291,"
            + "sh600267,sz002967,sz300267,sh603690,sh603730,sh601965,sz002838,sz002214,sz300598,sz002332,sz002777,"
            + "sz002950,sz300428,sz300638,sz300702,sz300765,sz300770,sz300775,sz300783,sh600458,sh600685,sh600775,"
            + "sh600971,sh601137,sh601567,sh603236,sh600993,sh601515,sh603169,sh603279,sz002034,sz002063,sz002123,"
            + "sz002400,sz002646,sz002913,sz300623,sz300723,sh600284,sh600389,sh600496,sh600635,sh600761,sh600810,"
            + "sh601519,sh603027,sh600773,sh600850,sh601606,sh603583,sz300634,sz002928,sz002851,sh601375,sh601886,"
            + "sh600059,sz000913,sz002428,sh603896,sz300602,sh600929,sh600422,sh603876,sh600211,sh603733,sz300039,"
            + "sz300725,sz002261,sh603666,sh600596,sh600933,sh600966,sz000810,sh600295,sh603466,sz000030,sz300735,"
            + "sz000923,sz300726,sz300666,sh601908,sz002267,sz000935,sz002727,sz002061,sh603801,sh600055,sh603533,"
            + "sz300158,sh601949,sh600217,sh603920,sh603881,sz000560,sz300633,sh603113,sz000550,sh603323,sz002237,"
            + "sh603043,sz300679,sz000951,sh600252,sh600783,sh600997,sh603298,sz300085,sz300527,sh600252,sh600783,"
            + "sh600997,sh603298,sh603919,sh603108,sz300236,sz000603,sz000688,sz000059,sz300457,sz300497,sz002675,"
            + "sz300366,sz300232,sh600072,sh600477,sh600876,sz300031,sz300109,sz300476,sh600110,sh600641,sh601011,"
            + "sz000735,sz002488,sz002747,sz300458,sh600986,sh603588,sh603979,sh603997,sz000657,sz002226,sz002737,"
            + "sh600123,sh600491,sh603609,sh603609,sh603678,sh600711,sh600449,sz002726,sz002378,sz002171,sz000902,"
            + "sz000035,sh600323,sh600662,sz002215,sh600420,sz002649,sz002643,sz300083,sz300185,sz002697,sh600363,"
            + "sh600559,sh600391,sz000789,sz002421,sz002605,sz002643,sz300083,sz300185,sz002697,sh600363,sh600559,"
            + "sh600604,sz002126,sz002597,sz002610,sz000058,sz002516,sz002677,sz002182,sz002617,sz002446,sz000811,"
            + "sz000901,sh600285,sh600063,sz002108,sh600360,sz002626,sz300339,sz300379,sh600621,sz000875,sh603008,"
            + "sh600116,sz002245,sh600480,sz002307,sz300377,sz002222,sz300130,sz002139";

    private static String ZZ1000_STOCK_CODE_LIST =
        "300415,603398,300475,000869,300618,002183,001287,002127,001337,002275,300741,002081,301262,301205,002901,"
            + "300482,002077,300620,300113,002250,002249,002985,000420,002096,301153,002705,002745,300261,002354,"
            + "002265,"
            + "002458,301246,001311,000837,000719,000415,300624,300182,002221,300182,300624,301262,301381,001287,"
            + "600012,"
            + "601326,600623,600976,603083,002275,300741,000719,002250,002458,603162,002221,002081,600409,600861,"
            + "600195,"
            + "002096,002265,600595,600782,301205,600601,600507,000869,301293,300261,001311,301358,002354,301376,"
            + "600718,"
            + "002183,601718,000420,001337,688381,688409,300741,002077,600409,000415,002183,000719,002250,002249,"
            + "688403,"
            + "000420,002705,002275,300482,688322,301262,688596,688327,600595,301325,688380,301291,002866,688209,"
            + "605020,"
            + "603719,603281,603100,000736,000552,601022,000821,000062,601101,603983,603477,000029,603057,000756,"
            + "601022,"
            + "301316,301267,600648,300820,688091,002840,688123,603871,600216,301363,600006,600064,301301,301327,"
            + "600313,"
            + "301171,300869,300630,603281,600633,600201,301165,300416,688110,002416,002242,300002,300693,002583,"
            + "002932,"
            + "002424,002396,002434,002948,688173,002701,603100,603719,601101,301363,600633,600201,600340,601019,"
            + "688326,"
            + "603100,688239,688238,688270,688261,688262,688235,688206,688048,688110,688173,688232,688337,688167,"
            + "688088,"
            + "603983,603719,603477,605333,688091,688190,605020,603888,603281,603871,000686,002053,002124,000552,"
            + "001236,"
            + "002060,301095,000990,001301,002124,301268,000028,002003,301207,688131,300315,000528,603297,601068,"
            + "002006,"
            + "601860,600403,002302,603123,300687,002011,688789,000690,600400,688676,600572,688798,600508,688707,"
            + "002233,"
            + "688559,300332,603197,301219,000737,300953,600037,688800,002946,301216,300358,300887,688660,002317,"
            + "600835,"
            + "688711,301238,688321,002815,301175,688499,603300,001270,603132,002004,601975,600120,002349,688575,"
            + "002174,"
            + "002549,600811,688518,300166,688739,603032,000488,600478,601068,301268,002006,603297,688131,300887,"
            + "600403,"
            + "301207,002317,002946,301216,300358,601860,301200,001258,000028,300315,002946,301216,002317,600478,"
            + "688660,"
            + "001258,600403,301047,300459,600908,002724,600888,300443,600163,688128,000681,603306,603567,688608,"
            + "603010,"
            + "688315,603396,300382,301089,603995,600691,300827,301080,600675,301180,600955,688083,300772,688686,"
            + "601702,"
            + "688383,600869,001213,300133,603505,301060,000982,688696,603055,301071,600691,300459,002038,600955,"
            + "002724,"
            + "688608,600163,301180,300827,301080,000422,600675,603010,688128,688686,688315,300772,688083,001213,"
            + "600888,"
            + "603396,000681,600869,601702,688383,300382,600610,605589,603306,600821,300133,600908,301047,300443,"
            + "000681,"
            + "600869,601702,688383,300382,600610,605589,603306,600821,300133,600908,301047,300443,603995,603567,"
            + "688356,"
            + "688586,000966,601208,600007,603033,600877,688127,688027,605090,688508,301015,300432,002612,002217,"
            + "003039,"
            + "605365,300671,002773,600098,601921,603171,300027,003040,000048,000061,688526,002534,002456,000761,"
            + "000860,"
            + "002176,002839,601777,600586,000727,688339,000762,688586,000966,688408,601208,600007,603033,600877,"
            + "688127,"
            + "688106,688027,605090,688508,301015,300432,002612,002217,003039,605365,300671,002773,600098,601921,"
            + "603171,"
            + "300027,003040,601528,000048,300035,603906,600428,002984,002941,688278,600017,002891,688333,300134,"
            + "600073,"
            + "600578,002807,000600,688318,003009,300151,300860,600100,600320,603187,002544,000767,000543,003006,"
            + "003012,"
            + "300087,300470,300894,300910,600151,600277,600338,600575,603179,601212,600682,002190,000927,000712,"
            + "603229,"
            + "603877,603565,605009,605111,688368,688389,605338,605376,688037,688023,688158,688100,688166,688198,"
            + "688202,"
            + "688268,688266,688298,688278,688333,688318,002993,003006,003009,603129,601609,300206,000848,603566,"
            + "600996,"
            + "002990,002979,603301,603766,688366,603208,688016,688018,603025,300080,300841,002978,300639,600557,"
            + "300856,"
            + "688019,688033,600395,688001,002987,688388,601311,300767,002541,601678,600874,300738,600770,300855,"
            + "000032,"
            + "002847,000828,603129,601609,300206,000848,603566,600996,002990,002979,603301,603766,688366,603208,"
            + "688016,"
            + "688018,603025,688007,600452,300653,002201,603936,600223,002960,002573,603005,002961,300119,002706,"
            + "002312,"
            + "300762,300663,300455,000006,603530,300579,000403,600246,601001,002194,002959,002015,600510,000503,"
            + "002291,"
            + "300573,600267,300792,002967,603489,300267,300803,603690,002838,603730,002214,601965,300598,002838,"
            + "603730,"
            + "002214,601965,300598,300525,002332,002489,002777,002832,002950,300327,300428,300596,300638,300662,"
            + "300702,"
            + "300761,300765,300768,300770,300773,300775,300777,300783,600169,600458,600587,600685,600750,600775,"
            + "600864,"
            + "600971,600993,601137,601515,601567,603169,603236,603279,600993,601137,601515,601567,603169,603236,"
            + "603279,"
            + "603915,002034,002041,002063,002100,002123,002276,002400,002498,002646,002741,002913,300401,300623,"
            + "300674,"
            + "300723,300755,600284,600366,600389,600483,600496,600618,600635,600710,600761,600773,600810,600850,"
            + "601519,"
            + "601606,603027,603583,600773,600810,600850,601519,601606,603027,603583,603713,300634,601330,002928,"
            + "603599,"
            + "002851,603363,601375,300123,601886,300233,600059,603013,000913,300451,002428,002929,603896,601619,"
            + "300602,"
            + "002698,600929,601677,600422,300143,603876,603728,600211,300725,603733,002261,300039,603666,300725,"
            + "603733,"
            + "002261,300039,603666,300747,600596,300685,600933,002292,600966,002895,000810,603595,600295,300398,"
            + "603466,"
            + "002911,000030,000791,300735,002158,000923,603103,300726,002906,300666,002020,601908,300567,002267,"
            + "000555,"
            + "000935,600055,002727,603533,002061,300158,603801,601949,600055,002727,603533,002061,300158,603801,"
            + "601949,"
            + "300393,600217,000672,603920,600612,603881,000968,000560,601952,300633,603612,603113,002859,000550,"
            + "002581,"
            + "603323,600812,002237,601918,603043,300613,300679,000917,000951,600075,600252,600456,600783,600797,"
            + "600997,"
            + "601126,603298,603393,300085,300323,300527,600075,600252,600456,600783,600797,600997,601126,603298,"
            + "603393,"
            + "603919,000650,603108,002314,300236,000034,000603,002782,000688,000885,000059,002537,300457,000795,"
            + "300497,"
            + "600963,002675,300409,300366,600490,300232,300476,600072,600110,600477,600641,600876,601011,300031,"
            + "300036,"
            + "300109,300456,300476,600072,600110,600477,600641,600876,601011,603299,000735,002335,002488,002651,"
            + "002747,"
            + "300348,300458,600550,600986,603118,603588,603718,603979,603989,603997,000498,000657,000928,002226,"
            + "002320,"
            + "002737,300406,600123,600197,600491,603368,603609,603636,603609,603636,603678,601890,600711,600531,"
            + "600449,"
            + "300065,002726,002585,002378,002206,002171,002135,000902,000065,000035,002151,600323,000801,600662,"
            + "300303,"
            + "002215,600331,600420,600330,002649,600502,002643,002130,300083,300188,300185,600459,002697,002218,"
            + "600363,"
            + "002389,600559,002139,600391,300224,000789,300229,002421,300034,002605,600502,002643,002130,300083,"
            + "300188,"
            + "300185,600459,002697,002218,600363,002389,600559,600621,600604,000875,002126,603008,002597,600116,"
            + "002610,"
            + "002245,000058,600480,002516,002307,002677,300377,002182,002222,002617,300130,002446,002139,000811,"
            + "002145,"
            + "000901,300284,600285,002567,600063,300294,002108,002283,600360,002351,002626,000016,300339,002097,"
            + "300379,"
            + "600577,600621,600604,000875,002126,603008,002597,600116,002610,002245,000058,600480,002516,002307,"
            + "002677," + "300377,002182,002222,002617,300130,002446,002139,002099";

    /**
     * 初始化中证1000股票信息
     */
    private static void initCode() {
        //System.out.println(content);
        List<String> codeList = Lists.newArrayList(ZZ1000_STOCK_CODE_LIST.split(","));
        codeList = codeList.stream().filter(t -> !t.startsWith("688")).collect(Collectors.toList());
        List<String> list = new ArrayList<>();
        for (int i = 0; i < codeList.size(); i++) {
            if (i % 2 == 0) {
                continue;
            }
            String code = codeList.get(i);
            if (code.startsWith("60")) {
                code = "sh" + code;
            } else {
                code = "sz" + code;
            }
            list.add(code);
        }
        System.out.println(StringUtils.join(list, ","));
    }

    public static void main(String[] args) {
        initCode();
    }
}
